﻿#include "frame.h"

#include <learn/ais/ais_builder.h>
#include <learn/ais/ais_curve.h>
#include <learn/ais/ais_mesh.h>
#include <learn/ais/ais_point.h>
#include <learn/ais/ais_surface.h>
#include <learn/ais/ais_vector.h>
#include <learn/alg/alg_approximator.h>
#include <learn/alg/alg_common_surface.h>
#include <learn/alg/alg_dynamic_curve.h>
#include <learn/alg/alg_dynamic_surface.h>
#include <learn/alg/alg_interpolator.h>
#include <learn/alg/alg_pia_curve.h>
#include <learn/alg/alg_pia_surface.h>
#include <learn/geom/geom_bezier_curve.h>
#include <learn/geom/geom_conic.h>
#include <learn/geom/geom_param_curve.h>
#include <learn/geom/geom_param_surface.h>
#include <learn/geom/geom_trimmed_curve.h>
#include <learn/gl/gl_renderer.h>
#include <learn/math/differential.h>
#include <learn/utils/output.h>

using namespace xi;
using namespace xi::gl;
using namespace xi::ais;
using namespace xi::alg;
using namespace xi::geom;
using namespace xi::math;

// 应用程序类
class GLApp : public CWinApp
{
  public:
    virtual BOOL InitInstance()
    {
#ifndef NDEBUG
        AllocConsole();
        FILE *pCout;
        freopen_s(&pCout, "CONOUT$", "w", stdout);
        freopen_s(&pCout, "CONOUT$", "w", stderr);

        SetConsoleOutputCP(CP_UTF8);
#endif

        // 创建流程
        CSingleDocTemplate *pTemplate =
            new CSingleDocTemplate(IDR_MENU1, RUNTIME_CLASS(GLDoc), RUNTIME_CLASS(GLFrame), RUNTIME_CLASS(GLView));

        // 添加模板
        AddDocTemplate(pTemplate);

        // 创建新的窗口
        OnFileNew();
        m_pMainWnd->ShowWindow(SW_SHOW);
        m_pMainWnd->UpdateWindow();
        m_pMainWnd->SetWindowText(L"GLFW");
        m_pMainWnd->SetWindowPos(NULL, 0, 0, 800, 600, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);

        // 构建 GLFW 上下文
        InitGL();

        return TRUE;
    }

    void InitGL()
    {
        auto frame = (CFrameWnd *)m_pMainWnd;
        RECT rect;
        frame->GetWindowRect(&rect);

        // 创建 context
        auto view = (GLView*)frame->GetActiveView();
        auto context = view->CreateContext(rect.right - rect.left, rect.bottom - rect.top)->context();

        // 注册对象
        // std::shared_ptr<AIS_Point> point(new AIS_Point(Vec3{0.0, 0.0, 1.0}));
        // context->add_object(point);
        // auto point = AIS_Builder::create_point(Vec3{0.0, 0.0, 1.0});
        // context->add_object(point);

        // auto point2 = AIS_Builder::create_point(Vec3{0.0, 1.0, 0.0});
        // context->add_object(point2);

        // auto point3 = AIS_Builder::create_point(Vec3{1.0, 0.0, 0.0});
        // context->add_object(point3);

        auto point4 = AIS_Builder::create_point(Vec3{1.0, 1.0, 1.0});
        context->add_object(point4);

        // std::vector<Vec3> points;
        // for (int i = 0; i < 100; i++)
        //     points.push_back(random_point<3>(-1.0, 1.0));
        // std::shared_ptr<AIS_PointCloud> pointCloud(new AIS_PointCloud(std::move(points)));
        // context->add_object(pointCloud);

        // {
        //     auto qcurve = std::make_shared<Geom_QR_BezierCurve<3>>(
        //         Vec3{0.0, 0.0, 0.0}, Vec3{0.0, 0.0, 0.0}, Vec3{2.0, 0.0, 0.0}, 0.0);
        //     qcurve->set_inf_pole(1, Vec4{0.0, 1.0, 0.0, 0.0});
        //     auto aisCurve = std::make_shared<AIS_Curve>(qcurve);
        //     context->add_object(aisCurve);
        // }

         {
             //auto vector = AIS_Builder::create_vector(Vec3{0.0, 0.0, 0.0}, Vec3{1.0, 1.0, 1.0});
             //context->add_object(vector);

             auto qcurve = std::make_shared<Geom_QR_BezierCurve<3>>(
                 Vec4{0.0, 0.0, 0.0, 1.0}, Vec4{0.0, 1.0, 0.0, 0.5}, Vec4{1.0, 1.0, 0.0, 1.0});
             auto aisCurve = AIS_Builder::create_curve(qcurve);
             context->add_object(aisCurve);
         }

         /*{
             auto curve = Geom_QR_BSplineCurve<3>::make_circle(
                 Vec3{0.0, 0.0, 0.0}, Vec3{0.0, 0.0, 1.0}, Vec3{1.0, 0.0, 0.0}, 10, degrees_to_radians(45.0),
                 degrees_to_radians(405.0));
             auto aisCurve = AIS_Builder::create_curve(curve);
             context->add_object(aisCurve);
         }*/

      /*   {
             auto curve = Geom_QR_BezierCurve<3>::make_one_arc(Vec3{0.0, 0.0, 0.0}, Vec3{0.0, 0.0, 1.0},
                                                                             Vec3{1.0, 0.0, 0.0}, Vec3{0.0, 0.0,
                                                                             -1.0}, Vec3{0.5, 0.0, 1.0});
             auto aisCurve = AIS_Builder::create_curve(curve);
             context->add_object(aisCurve);
         }*/

        // {
        //     std::vector<Vec4> points(6);
        //     points[0] = Vec4{0.0, 0.0, 0.0, 1.0};
        //     points[1] = Vec4{1.0, 0.0, 0.0, 0.5};
        //     points[2] = Vec4{1.0, 1.0, 0.0, 2.0};
        //     points[3] = Vec4{0.0, 1.0, 0.0, 3.0};
        //     points[4] = Vec4{0.0, 0.0, 1.0, 0.5};
        //     points[5] = Vec4{1.0, 0.0, 1.0, 1.0};
        //     std::vector<double> knots = {0, 0, 0, 0, 0.3, 0.7, 1.0, 1.0, 1.0, 1.0};
        //     auto curve = std::make_shared<Geom_BSplineCurve<3, true>>(std::move(points), std::move(knots), 3);

        //     curve->reparam(2, 1, 3, 2);

        //     std::cout << curve->knots() << std::endl;
        //     std::cout << curve->poles() << std::endl;

        //     auto aisCurve = AIS_Builder::create_curve(curve);
        //     context->add_object(aisCurve);
        // }

        // {
        //     auto curve =
        //         Geom_QR_BezierCurve<3>::make_one_arc(Vec3{0.0, 0.0, 0.0}, Vec3{-1.0, 0.0, 1.0}, Vec3{1.0, 0.0, 0.0},
        //                                              Vec3{0.0, 0.0, -1.0}, Vec3{0.5, 0.0, 1.0});
        //     auto [c1P, c2P] = curve->split_at_shoulder_point();
        //     auto aisCurve1 =
        //         AIS_Builder::create_curve(std::make_shared<Geom_BezierCurve<3, true>>(std::move(c1P), 2, false));
        //     auto aisCurve2 =
        //         AIS_Builder::create_curve(std::make_shared<Geom_BezierCurve<3, true>>(std::move(c2P), 2, false));
        //     auto aisCurve3 = AIS_Builder::create_curve(curve);
        //     context->add_object(aisCurve1);
        //     context->add_object(aisCurve2);
        //     context->add_object(aisCurve3);
        // }

        // {
        // std::vector<Vec3> poles(4);
        // poles[0] = Vec3{0.0, 0.0, 0.0};
        // poles[1] = Vec3{0.0, 1.0, 0.0};
        // poles[2] = Vec3{1.0, 1.0, 0.0};
        // poles[3] = Vec3{1.0, 0.0, 0.0};
        // std::shared_ptr<Geom_BezierCurve<3>> curve(new Geom_BezierCurve<3>(std::move(poles)));
        // // std::shared_ptr<AIS_Curve> acurve(new AIS_Curve(curve));
        // auto acurve = AIS_Builder::create_curve(curve);
        // context->add_object(acurve);

        //     auto [cpts1, cpts2] = curve->split(0.75);
        //     auto curve1 = std::make_shared<Geom_BezierCurve<3>>(std::move(cpts1));
        //     auto curve2 = std::make_shared<Geom_BezierCurve<3>>(std::move(cpts2));
        //     std::shared_ptr<AIS_Curve> acurve1(new AIS_Curve(curve1));
        //     std::shared_ptr<AIS_Curve> acurve2(new AIS_Curve(curve2));
        //     context->add_object(acurve1);
        //     context->add_object(acurve2);

        //     poles.resize(4);
        //     poles[0] = Vec3{0.0, 0.0, 1.0};
        //     poles[1] = Vec3{0.0, 1.0, 1.0};
        //     poles[2] = Vec3{1.0, 1.0, 1.0};
        //     poles[3] = Vec3{1.0, 0.0, 1.0};
        //     std::shared_ptr<Geom_BezierCurve<3>> curve3(new Geom_BezierCurve<3>(std::move(poles)));
        //     std::shared_ptr<AIS_Curve> acurve3(new AIS_Curve(curve3));
        //     context->add_object(acurve3);
        // }

        {
            std::shared_ptr<AIS_Frame> frame(new AIS_Frame(0, 0, 100, 100));
            context->add_object(frame);
        }
    }

    ~GLApp()
    {
#ifndef NDEBUG
        FreeConsole();
#endif
    }
};

// 应用程序对象的全局变量
GLApp theApp;